package com.sdk.server;

import com.sdk.business.SessionService;
import com.sdk.business.StakeService;
import com.sdk.constant.HttpMethod;
import com.sdk.constant.HttpStatus;
import com.sdk.dto.OfferStakeDto;
import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpHandler;

import java.io.IOException;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;

public class HttpServerHandler implements HttpHandler {

    private final SessionService sessionService;

    private final StakeService stakeService;

    public HttpServerHandler(SessionService sessionService, StakeService stakeService) {
        this.stakeService = stakeService;
        this.sessionService = sessionService;
    }

    @Override
    public void handle(HttpExchange exchange) throws IOException {
        String path = exchange.getRequestURI().getPath();
        String method = exchange.getRequestMethod();

        if (HttpMethod.GET.getCode().equals(method) && path.matches("/\\d+/session")) {
            handleCreateSession(exchange);
        } else if (HttpMethod.POST.getCode().equals(method) && path.matches("/\\d+/stake")) {
            handleOfferStake(exchange);
        } else if (HttpMethod.GET.getCode().equals(method) && path.matches("/\\d+/highstakes")) {
            handleListHighStakes(exchange);
        } else {
            sendErrorResponse(exchange, "Not Found", HttpStatus.NOT_FOUND.getCode());
        }
    }

    private void handleCreateSession(HttpExchange exchange) throws IOException {
        String customerId = parseCustomerIdFromPath(exchange.getRequestURI().getPath());
        String sessionId = sessionService.createSession(customerId);
        sendResponse(exchange, sessionId, HttpStatus.OK.getCode());
    }

    private void handleOfferStake(HttpExchange exchange) throws IOException {
        String stake = new String(exchange.getRequestBody().readAllBytes(), StandardCharsets.UTF_8);
        String betOfferId = parseBetOfferIdFromPath(exchange.getRequestURI().getPath());
        String sessionKey = getQueryParameter(exchange.getRequestURI().getQuery(), "sessionkey");

        String customerId = sessionService.getCustomerId(sessionKey);
        if (customerId == null) {
            sendErrorResponse(exchange, "Invalid Session Key", HttpStatus.ERROR.getCode());
            return;
        }
        OfferStakeDto offerStakeDto = new OfferStakeDto();
        offerStakeDto.setBetOfferId(String.valueOf(betOfferId));
        offerStakeDto.setCustomerId(customerId);
        offerStakeDto.setStake(Integer.valueOf(stake));
        stakeService.offerStake(offerStakeDto);

        String responseBody = "";
        sendResponse(exchange, responseBody, HttpStatus.OK.getCode());
    }

    private void handleListHighStakes(HttpExchange exchange) throws IOException {
        String betOfferId = parseBetOfferIdFromPath(exchange.getRequestURI().getPath());
        String highStakes = stakeService.listHighStakes(betOfferId);
        sendResponse(exchange, highStakes, HttpStatus.OK.getCode());
    }

    private String parseCustomerIdFromPath(String path) {
        return parsePathPart(path, 1);
    }

    private String parseBetOfferIdFromPath(String path) {
        return parsePathPart(path, 1);
    }

    private String parsePathPart(String path, int partIndex) {
        String[] parts = path.split("/");
        if (partIndex < 0 || partIndex >= parts.length) {
            throw new IllegalArgumentException("Invalid path format");
        }
        return parts[partIndex];
    }

    private String getQueryParameter(String query, String name) {
        if (query == null) {
            return null;
        }
        String[] pairs = query.split("&");
        for (String pair : pairs) {
            int idx = pair.indexOf("=");
            if (idx > 0 && pair.substring(0, idx).equals(name)) {
                return pair.substring(idx + 1);
            }
        }
        return null;
    }

    private void sendResponse(HttpExchange exchange, String responseBody, int statusCode) throws IOException {
        exchange.sendResponseHeaders(statusCode, responseBody.getBytes().length);
        OutputStream os = exchange.getResponseBody();
        os.write(responseBody.getBytes());
        os.close();
    }

    private void sendErrorResponse(HttpExchange exchange, String message, int statusCode) throws IOException {
        String responseBody = "error=" + message;
        exchange.sendResponseHeaders(statusCode, responseBody.getBytes().length);
        OutputStream os = exchange.getResponseBody();
        os.write(responseBody.getBytes());
        os.close();
    }
}
